03 فصل سوم - تفکر پایتونی

فصل سه

توابع

۳.۱ فراخوانی تابع

در برنامه‌نویسی، تابع دنباله‌ای دارای نام از دستورات است که محاسبه‌ای را انجام می‌دهد. (در برنامه‌نویسی، به دنباله‌ای دارای نام از دستورات که محاسبه‌ای را انجام می‌دهد تابع گفته می‌شود.) هنگام تعریف تابع، شما نام و دنباله دستورات آن را مشخص می‌کنید. بعدا شما می‌توانید به وسیله نام تابع آن را «فراخوانی» کنید. در فصل‌های پیشین یک مثال از فراخوانی تابع را مشاهده کردید:

>>> type(32)

<type ' int' >

در این مثال type نام تابع است. عبارتی که درون پرانتز است آرگمان تابع نام دارد. نتیجه تابع (در این مثال) نوع آرگمان را مشخص می‌کند.

گفتن اینکه یک تابع، آرگمان ورودی را «می‌گیرد» و نتیجه را «برمی‌گرداند» بسیار رایج است. به نتیجه تابع مقدار برگشتی گفته می‌شود.

در پایتون توابع پیش‌فرضی وجود دارند که با استفاده از آنها می‌توان مقادیر یک نوع داده را به نوع دیگر تبدیل کرد. تابع int هر مقداری را به عنوان آرگمان ورودی می‌گیرد و در صورت امکان آن را به نوع داده‌ای صحیح تبدیل می‌کند. در صورتی‌که امکان تبدیل نوع وجود نداشته باشد؛ خطای مناسب نمایش داده می‌شود.

>>> int(' 32' )

32

>>> int(' Hello' )

ValueError: invalid literal for int(): Hello

تابع int می‌تواند مقادیر اعشاری (ممیز شناور) را به نوع داده‌ای صحیح تبدیل کند. این تابع اعداد اعشاری را گِرد (رُند) نمی‌کند، بلکه قسمت اعشاری را حذف می‌کند.

>>> int(3.99999)

3

>>> int(-2.3)

-2

تابع float اعداد صحیح و رشته‌ها (string) را به عدد اعشاری تبدیل می‌کند.

>>> float(32)

32.0

>>> float(' 3.14159' )

3.14159

نهایتا تابع str آرگمان ورودی را به نوع داده‌ی رشته‌ای تبدیل می‌کند.

>>> str(32)

' 32'

>>> str(3.14159)

' 3.14159'

۳.۲ توابع ریاضی

پایتون یک ماژول ریاضی دارد که اکثر توابع ریاضی معروف در آن موجود است. ماژول، فایلی است که مجموعه‌ای از توابع مرتبط به هم را در خود دارد.

پیش از استفاده کردن از هر ماژول، باید به وسیله دستور import آن‌را به برنامه وارد کرد.

>>> import math

این دستور یک شی از نوع ماژول و به نام math را ایجاد می‌کند. در صورتی‌که شما از دستور print برای این شی استفاده کنید؛ برخی از اطلاعات این ماژول نمایش داده خواهد شد.

>>> print math

<module ' math' (built-in)>

شی ماژول، حاوی توابع و متغیرهای موجود در آن ماژول است. برای دسترسی به توابع موجود در یک ماژول از قالبی که به نمادگذاری نقطه‌ای (dot notation) معروف است؛ استفاده می‌شود. در این قالب نام ماژول و تابع مورد نظر به وسیله نقطه از یکدیگر جدا می‌شود.

>>> ratio = signal_power / noise_power

>>> decibels = 10 * math.log10(ratio)

>>> radians = 0.7

>>> height = math.sin(radians)

در مثال اول برای محاسبه نسبت سیگنال به نویز بر حسب دسی‌بل از تابع log10 استفاده شده است (فرض شده متغیرهای signal_power و noise_power قبلا تعریف شده‌اند). همچنین در ماژول math تابع log که لگاریتم در مبنای e را محاسبه می‌کند؛ موجود است.

مثال دوم سینوس متغیر radians را محاسبه می‌کند. باید در نظر داشت که آرگمان ورودی تابع sin و سایر توابع مثلثاتی (cos، tan و ...) موجود در این ماژول می‌بایست برحسب رادیان باشند. برای تبدیل درجه به رادیان، باید درجه را بر (360 * 2π)‌ تقسیم کرد.

>>> degrees = 45

>>> radians = degrees / 360.0 * 2 * math.pi

>>> math.sin(radians)

0.707106781187

عبارت math.pi مقدار متغیر pi را از ماژول math دریافت می‌کند. مقدار این متغیر، تقریبی از عدد π با دقت ۱۵ رقم است.

درصورتی‌که ریاضیات مثلثاتی را به یاد داشته باشید؛ با تقسیم کردن جذر عدد دو بر دو نتیجه مثال قبل را می‌توان بررسی کرد.

>>> math.sqrt(2) / 2.0

0.707106781187

۳.۳ ترکیب

تاکنون ما به عناصر مختلف یک برنامه نگاه کرده ایم ، متغیر ها ، عبارات و دستورات را به صورت جدا از هم بررسی کرده ایم بدون آنکه درباره ی چگونگی ترکیب آن ها صحبتی کرده باشیم .

یکی از مفیدترین قابلیت زبان های برنامه نویسی قابلیت ترکیب بلاک های کوچکی از کد با یک دیگر است . به عنوان مثال آرگومان یک تابع میتواند هر گونه عبارتی شامل عملیات های ریاضی باشد

x = math.sin(degrees / 360.0 * 2 * math.pi)

و حتی صدا زدن توابع

x = math.exp(math.log(x+1))

تقریبا در هرجایی که میتوانید یک مقدار را قرار دهید ، میتوانید یک عبارت دلخواه قرار دهید\ با یک استثنا . سمت چپ عبارت باید اسم یک متغیر باشد . قرار دادن هر عبارت دیگری در سمت چپ باعث Syntax Error می شود (در آینده با استثنا های این قاعده آشنا خواهیم شد)

>>> minutes = hours * 60 #right

>>> hours * 60 = minutes #wrong!

SyntaxError: can’t assign to operator

#### ۳.۴ اضافه کردن توابع جدید

تابه این جا ، فقط از توابعی استفاده کرده ایم که به طور درونی در خود پایتون وجود داشته اند ولی این امکان وجود دارد که خودمان هم توابعی را تعریف کنیم . یک تعریف تابع نام تابع جدید و ترتیب عباراتی که پس از فراخوانی تابع اجرا میشوند را مشخص میکند

def print_lyrics():

print(“i ‘, a lumberjack , and I’m okay.”)

print(“I sleep all night and I work all day”)

def کلمه ی کلیدی است که مشخص میکند این یک تعریف تابع است .نام تابع print_lyrics است . قواعد نام های تابع مانند نام های متغیرها هستند:حروف ، اعداد و "_" مجازند ولی حرف اول نمیتواند یک عدد باشد. و شما نمیتوانید یک کلمه ی کلیدی را به عنوان نام تابع انتخاب کنید مثلا while یا if نمیتوانند به عنوان نام تابع انتخاب شوند و شما باید از استفاده از یک نام هم به عنوان نام تابع هم به عنوان نام متغیر پرهیز کنید

پرانتز های خالی بعد نام مشخص میکنند که این تابع هیچ آرگومانی را نمیگیرد\ اولین خط تعریف تابع header نامیده میشود و باقی خطوط body نامیده میشوند . header با یک : پایان میپذیرد و بخش body باید تورفته باشد . عرف اینگونه است که تورفتگی همیشه به اندازه ۴ عدد space است . بخش body میتواند شامل هرچند خط عبارت باشد

رشته ها در عبارات print توسط " احاطه شده اند. ' و " یک کار را انجام میدهند.اکثر مواقع افراد از ' استفاده میکنند مگر در مواردی که ' در خود رشته استفاده شده است.

همه ی کوتیشین ها چه تکی چه دوتایی باید کوتیایشین صاف باشند. که معمولا در کیبورد دکمه ی کنار دکمه ی Enter می باشند . کوتیشین های کج مانند ” در پایتون مجاز نیستند.

اگر شما در شل پایتون و در حالت تعاملی یک تابع را تایپ کنید مفسر پایتون نقطه های (...) تا به شما نشان دهد که تعریف تابع همچنان کامل نشده است.

\ >>> def print_lyrics():

… print(“I’m a lumberjack , and I’m okay.”)

… print(“I sleep all night and I work all day.”)

برای اتمام تابع شما باید یک خط خالی تایپ کنید

تعریف یک تابع یک شی تابع میسازد که نوع تابع را دارد

>>> print (print_lyrics)

<function print_lyrics at 0xb7e99e9c>

>>> type(print_lyrics)

<class ‘function’>

سینتکس استفاده از تابع جدید همانند استفاده از توابع های درونی پایتون است

>>> print_lyrics()

I’m a lumberjack, and I’m okay.

I sleep all night and i work and day.

به محض اینکه یک تابع را تعریف کردید میتوانید آن را داخل یک تابع دیگر استفاده کنید. به عنوان مثال برای تکرار مرحله قبل , ما میتوانیم یک تابع به اسم repeat_lyrics بنویسیم:

def repeat_lyrics():

print_lyrics()

print_lyrics()

و تابع repeat_lyrics را صدا بزنیم:

>>> def print_lyrics():

I’m a lumberjack, and I’m okay.

I sleep all night and i work all day.

I’m a lumberjack and I’m okay.

I sleep all night and i work all day.

ولی در حقیقت آهنگ اینگونه ادامه پیدا نمیکند.

#### ۳.۵ تعاریف و استفاده ها

با جمع بندی تکه های کد از بخش قبلی , کل برنامه اینگونه بنظر میرسد:

def print_lyrics():

print(“I’m a lumberjack, and I’m okay,”)

print(“I sleep all night and I work all day.”)

def repeat_lyrics():

print_lyrics()

print_lyrics()

repeat_lyrics()

این برنامه شامل دو تعریف تابع است : print_lyrics و repeat_lyrics

تعاریف تابع مانند بقیه ی عبارات اجرا میشوند ولی حاصل اجرای آن ها اشیا تابع[^1] است.

عبارات داخل توابع تا زمانی که تابع فراخوانی نشوند اجرا نمیشوند و تعریف های توابع خروجی ای تولید نمیکند. {توضیح مترجم} به عبارت دیگر مقداری را return نمیکند

همانگونه که انتظار دارید , شما باید قبل از استفاده از یک تابع آن تابع را تعریف کنید.به عبارت دیگر , تعریف تابع باید قبل از اینکه تابع فراخوانی شود اجرا شود

به عنوان تمرین , اخرین خط برنامه فوق را به بالای برنامه ببرید.بنابراین , استفاده از تابع بالاتر از تعریف تابع قرار میگیرد . برنامه را اجرا کنید و ببینید چه پیغام خطا [^2]ای میگیرید

حال صدا زدن تابع(استفاده از تابع) را به پایین برنامه برگردانید و تعریف print_lyrics را به بعد از repeat_lyrics ببرید. حال چه تغییری در برنامه شما ایجاد می شود؟.

#### ۳.۶روند اجرا

برای اینکه مطمئن شویم که تابع قبل از اولین استفاده , تعریف شده است , ما باید ترتیبی که عبارات به ان اجرا میشوند را بدانیم که روند اجرا[^3] نامیده میشود.

اجرا همیشه با اولین عبارت برنامه شروع میشود.در هر لحظه یک عبارت اجرا میشود و این روال از بالا به پایین برنامه ادامه میابد.

تعاریف تابع روال اجرا را تغییر نمیدهند و به یاد داشته باشید که عبارات داخل تابع تا زمانی که تابع فراخوانی نشود اجرا نمی شوند.

فراخوانی توابع مانند یک مسیرانحرافی برای روند اجرا عمل میکنند. به جای رفتن به عبارت بعدی , روند به داخل بدنه ی تابع میرود و عبارات درون آن را اجرا میکند.سپس برمیگردد و اجرای را آنجا که رها کرده بود ادامه میدهد.

این قضیه ساده به نظر میرسد ولی به یاد داشته باشید یک تابع میتواند تابع دیگری را صدا بزند.در میان اجرای یک تابع , برنامه ممکن است مجبور باشد عباراتی را در یک تابع دیگر را اجرا کند. و در آن تابع ممکن است مجبور شود عبارات تابع دیگری را هم اجرا کند!

خوشبختانه , پایتون به خوبی میتواند به خوبی مسیری که در آن قرار دارد را شناسایی کند و به یاد بیاورد و هر بار که اجرای یک تابع را به پایان میرساند , از جایی که تابع به اتمام رسیده صدا زده شده اجرای برنامه را ادامه میدهد و هر وقت به انتهای برنامه برسد , اجرای آن را به اتمام میرساند.

به طور خلاصه , وقتی شما یک برنامه را میخوانید , به طور عادی از خط اول تا خط آخر را به شکل پشت سر هم نمیخوانید و بهتر است که روند اجرا را رعایت کنید تا با طرز کار آن برنامه بهتر آشنا شوید.

#### ۳.۷ پارامتر^4 ها و آرگومان ها

بعضی از توابعی که ما تاکنون دیده ایم نیاز به آرگومان دارند. به طور مثال وقتی شما math.sin را صدا میزنید , یک عدد را به عنوان آرگومان به تابع ارجاع میدهید تا تابع سینوس آن عدد را محاسبه کند.بعضی توابع بیش از یک آرگومان را دریافت میکنند :math.pow دو آرگومان دریافت میکند عدد و توان موردنظر برای عدد

درون تابع , آرگومان ها به مقادیری به نام پارامتر ها ارجاع داده می شوند. در اینجا مثالی از تعریف یک تابع تابع را میبینیم که یک آرگومان میپذیرد.

def print_twice(bruce):

print(bruce)

print(bruce)

این تابع آرگومان را به متغیری به نام bruce ارجاع میدهد.هنگامی که تابع صدا زده می شود , تابع مقدار پارامتر را دوبار چاپ میکند.

این تابع با هر مقداری که امکان چاپ شدن را داشته باشد کار میکند.

>>> print_twice(‘Spam’)

Spam

Spam

>>> print_twice(42)

42

42

>>>print_twice(math.pi)

3.14159265359

3.14159265359

همان قواعد ترکیب که برای توابع توکار پایتون استفاده میشدند برای توابعی که برنامه نویس تعریف میکند نیز اعمال می شود. به همین دلیل ما میتوانیم هر نوع عبارت^5 را به عنوان آرگومان به تابع ارسال کنیم

>>> print_twice(‘Spam ‘*4)

Spam Spam Spam Spam

Spam Spam Spam Spam

>>> print_twice(math.cos(math.pi))

-1.0

-1.0

قبل از صدا زدن تابع , مقدار آرگومان محاسبه می شود پس مثال های بالا عبارات

‘Spam ‘*4

و

math.cos(math.pi)

تنها یک بار محاسبه می شوند و برای چاپ دوم محاسبه مجددا انجام نمیشود

همچنین ما میتوانیم از متغیر ها به عنوان آرگومان استفاده کنیم

>>> michael = ‘Eric, the half a bee.’

>>> print_twice(michael)

Eric, the half a bee.

Eric, the half a bee.

نام متغیری که ما به تابع ارجاع میدهیم (michael) هیچ ارتباطی با نام پارامتر (bruce)ندارد.اهمیتی ندارد متغیر در صدازننده چه نام داشت , در print_twice همه با نام bruce صدا زده می شوند.

#### ۳.۸ متغیر ها و پارامتر ها محلی هستند

وقتی شما یک متغیر درون یک تابع می سازید , آن متغیر^6 محلی است. که به این معنی است که تنها درون آن تابع وجود دارد. به عنوان مثال:

def cat_twice(part1, part2):

cat = part1 + part2

print_twice(cat)

این تابع دو آرگومان میگیرد ,‌ آن دو را به هم الحاق می کند , و نتیجه را دوبار چاپ میکند.

در اینجا یک مثال از استفاده از این تابع را میبینیم:

>>> line1 = ‘Bing tiddle ‘

>>> line2 = ‘tiddle bang’

>>> cat_twice(line1, line2)

Bing tiddle tiddle bang.

Bing tiddle tiddle bang.

هنگامی که اجرای cat_twice به پایان می رسد , متغیر cat پاک می شود و اگر ما سعی کنیم آن را چاپ کنیم , یک استثناء^7 مواجه می شویم.

>>>print (cat)

NameError: name ‘cat’ is not defined.

پارامتر ها نیز به صورت محلی ایجاد و استفاده می شوند. به طور مثال در خارج از print_twice چیزی به نام bruce وجود ندارد.

#### ۳.۹ نمودار های پشته[^8]

برای آگاهی از این که کدام متغیر در کدام بخش از برنامه استفاده شده است بعضی مواقع رسم یک نمودار پشته مفید است. مانند نمودار های حالت[^9] , نمودار های پشته مقدار هر متغیر را نشان می دهند ولی تابعی که متغیر به آن تعلق دارد را نیز نمایش می دهند.

هر تابع با یک قاب ^10نمایش داده می شود. هر قاب یک مستطیل است که نام تابع در کنار آن و نام پارامتر ها و متغیر های تابع درون آن نوشته می شوند.

نمودار پشته ی مثال قبل درشکل 3.1 نشان داده شده است.

قاب ها در یک پشته دسته بندی دسته بندی شده اند که مشخص میکند کدام متغیر کدام را صدا زده است.در این مثال ,‌ print_twice توسط cat_twice صدا زده شده است و cat_twice توسط ــmain__ صدا زده شده است که یک نام ویژه برای بالاترین قاب است . وقتی شما یک متغیر خارج از تمام توابع و در بدنه اصلی برنامه تعریف می کنید , آن متغیر به __main__ تعلق دارد.هر پارامتر به مقدار آرگومان نظیرش اشاره می کند به همین دلیل part1 مقداری برابر line1 دارد و part2 مقداری برابر line2 دارد و مقدار bruce نیز با مقدار cat برابر است.

اگر در هنگام صدا زدن یک تابع مشکلی به وجود بیاید , پایتون نام تابع ,‌ نام تابعی که آن را صدا زده است و نام تابعی که تابع در حال صدا کردن تابع بالایی است و به همین ترتیب نام تمام توابع تا رسیدن به __main__ را چاپ می کند. به عنوان مثال اگر شما بخواهید از print_twice به cat دسترسی داشته باشید یک NameError دریافت خواهید کرد:

Traceback (innermost last):

File “test.py, Line 13, in __main__

cat_twice(line1, line2)

File “test.py”, Line5, in cat_twice

print_twice(cat)

File “test.py”, Line 9m in print_twice

print(cat)

NameError: name ‘cat’ os not defined

لیست توابع یک لیست ردیابی^11 نام دارد . لیست ردیابی به شما می گوید که مشکل ایجاد شده در کدام فایل برنامه و در کدام خط به وجود آمده است و در لحظه بروز خطا کدام تابع در حال اجرا بوده است همچنین خطی را که باعث ایجاد اشکال شده است را به شما نمایش می دهد.

ترتیب توابع در لیست ردیابی مانند ترتیب ترتیب توابع در نمودار پشته است و تابعی که اخیرا در حال اجرا بوده در پایین لیست مشاهده می شود.

#### ۳.۱۰ توابع با نتیجه [^12]و توابع بی نتیجه[^13]

بعضی از توابعی که ما تاکنون استفاده کرده ایم مانند توابع ریاضی , نتیجه ای را برمیگردانند از این به بعد این توابع را توابع با نتیجه می نامیم. سایر توابع مانند print_twice عملی را انجام می دهند ولی مقداری را برنمیگردانند.این توابع را توابع بی نتیجه می نامیم.

هنگامی که ما یک تابع با نتیجه را صدا میزنیم , در اکثر مواقع ما نیاز به نتیجه ی تابع داریم , به عنوان مثال شما ممکن یک آن را به یک متغیر ارجاع دهید یا آن را به عنوان بخشی از یک عبارت استفاده کنید:

x = math.cos(radians)

golden = (math.sqrt(5) + 1) / 2

وقتی شما یک تابع را در حالت تعاملی صدا می زنید ، پایتون نتیجه را چاپ می کند:

>>> math.sqrt(5)

2.23606797749979

ولی در یک برنامه ، اگر شما یک تابع بانتیجه را به تنهایی فراخوانی کنید ، مقدار برگردانده شده نادیده گرفته می شود!

math.sqrt(5)

این برنامه ریشه دوم عدد ۵ را محاسبه می کند ولی حاصل را در جایی ذخیره نمی کند و نمایش نمی دهد پس این روش چندان قابل استفاده نیست.

توابع بی نتیجه ممکن که چیزی را روی چاپ کنند یا تاثیرات دیگری داشته باشند ولی مقداری را برنمیگردانند.

اگر شما نتیجه را به یک متغیر ارجاع دهید ، یک مقدار خاص به نام None دریافت خواهید کرد:

>>> result = print_twice (“Bing”)

Bing

Bing

>> print(result)

None

مقدار None با مقدار رشته ی 'None' برابر نیست. این یک مقدار خاص با نوع خودش است:

>>> print (type(None))

<class ‘NoneType’)

توابعی که ما تا به حال نوشته ایم همگی بی نتیجه بوده اند. در چند فصل آینده ما شروع به نوشتن توابع بانتیجه خواهیم کرد.

####
#### ۳.۸ چرا توابع؟

شاید واضح نباشد که چرا ما باید به خودمان زحمت بدهیم و یک برنامه را به تعدادی تابع بشکنیم

برای این کار دلایل زیادی وجود دارد:

  • ساخت یک تابع جدید به ما این امکان را میدهد تا دسته ای از عبارات را نام گذاری کنیم که خواندن و خطایابی برنامه ما را آسان تر میکند
  • توابع میتوانند برنامه را با کم کردن خط های تکراری کوچک کنند ، هر تغییری در آینده هم لازم است فقط در یک محل اعمال شود
  • شکستن یک برنامه ی طولانی به توابع به شما این امکان را میدهد تا در ابتدا تک تک قسمت ها را اشکال زدایی کنید سپس تمام آن ها را به یک برنامه یکپارچه ای که کار می کند سرهم کنید.
  • توابعی که به خوبی طراحی شده باشند معمولا قابل استفاده در تعداد زیادی از برنامه ها هستند به محض آن که شما یکی از آن را بنویسید و آن را اشکال زذایی کنید ، میتوانید بعدا دوباره از آن تابع استفاده کنید
#### ۳.۱۲ اشکال زدایی^14

یکی از مهم ترین مهارت هایی که خواهید آموخت اشکال زدایی است.با وجود اینکه ممکن است خسته کننده به نظر برسد، اشکال زدایی یکی از فکری ترین و چالش برانگیز ترین و جذاب ترین بخش های برنامه نویسی است. از جنبه ای اشکال زدایی مانند کارآگاهی است.شما با سرنخ هایی مواجه هستید و باید به پروسه ها و رویداد هایی که نتایج فعلی ختم شده اند پی ببرید.

اشکال زدایی همچنین مانند علوم تجربی است . به ذهن شما یک ایده درباره ی چیزی که ایجاد مشکل می کند می رسد ، برنامه را دستکاری می کنید و دوباره امتحان می کنید. اگر فرضیه شما درست بوده باشد شما می توانید نتیجه دستکاری را پیشبینی کنید و یک قدم به برنامه ای که درست کار میکند نزدیک می شوید.اگر فرضیه شما اشتباه بوده باشد شما با یک فرضیه دیگر دوباره امتحان خواهید کرد. همانگونه که شرلوک هلمز اشاره [^15]کرده است:

هنگامی که شما غیرممکن را حذف کرده باشید ، هر چه باقی مانده باشد هر چقدر هم غیرمحتمل باید حقیقت داشته باشد.

برای بعضی از مردم ، برنامه نویسی و اشکال زدایی یک چیز هستند. در حقیقت برنامه نویسی را به چشم اشکال زدایی رفته رفته یک برنامه تا رسیدن به وضعیتی که برنامه کاری که شما انتظار دارید انجام دهد نگاه می کنند.ایده ی اصلی این است که شما با یک برنامه که کارش را به درستی انجام می دهد کار خود را شروع میکنید ، رفته رفته تغییرات کوچکی را اضافه میکنید و آن ها را اشکال زدایی میکنید و این روال را ادامه میدهید.

به عنوان مثال ، لینوکس یک سیستم عامل است که شامل میلیون ها خط از کد است ولی از یک برنامه کوچک که لینوس توروالدز[^16] برای کشف قابلیت های یک چیپ Intel 80386 نوشت شروع شد. طبق گفته ی لری گرینفیلد : یکی از پروژه های اولیه لینوس یک برنامه بود که بتواند بین چاپ کردن AAAA و ‌‌BBBB جابه حا شود.بعدا این برنامه به لینوکس تکامل یافت( The Linux Users' Guide Beta Version 1)

#### ۳.۱۳ لغت نامه

تابع:یک دسته ی نام گذاری شده از عبارات که یک عملیات مفید را انجام می دهد.توابع میتواند آرگومان بگیرند و می توانند یک نتیچه تولید کنند.

تعریف تابع:یک عبارت که یک تابع جدید تولید میکند،‌نام پارامتر ها و عباراتی که سازنده آن هستند را تعیین می کند.

شی تابع:یک مقدار که توسط یک تعریف تابع ساخته می شود. نام تابع مقداری است که به شی تابع اشاره دارد

هدر:اولین خط تعریف تابع است

بدنه:ترتیبی از عبارات درون تابع که تشکیل دهنده ی تابع است نام دارد.

پارامتر:نامی که داخل یک تابع برای مقداری که به عنوان آرگومان ارجاع داده شده است استفاده می شود

صدا زدن تابع: یک عبارت که یک تابع را اجرا می کند از نام تابع به همراه لیست آرگومان ها که داخل پرانتز قرار گرفته اند تشکیل می شود.

آرگومان:یک مقدار که هنگام فراخوانی تابع به تابع داده می شود. مقدار به پارامتر نظیر در تابع ارجاع داده می شود.

متغیر محلی:یک متغیر که درون تابع تعریف می شود.یک متغیر محلی تنها درون تابع قابل استفاده است

برگرداندن مقدار:حاصل اجرای یک تابع است اگر تابع توسط یک عبارت فراخوانی شده باشد،‌مقدار برگردانده شده برابر آن عبارت می شود.

تابع بانتیجه:یک تابع که مقداری را برمیگرداند

تابع بی نتیجه:یک تابع که همیشه None را برمیگرداند

یک متغیر خاص که توسط توابع بی نتیجه برگردانده می شودNone:

ماژول:یک فایل که حاوی مجموعه ای از توابع مرتبط به هم و سایر تعاریف است.

عبارتimport: یک عبارت که یک فایل ماژول را می خواند و یک شی ماژول می سازد

شی ماژول:یک مقدار که توسط عبارت Import ایجاد می شود که دسترسی به مقادیر تعریف شده در ماژول ها را ممکن می سازد

نشانه گذاری با نقطه:یک نحو برای صدازدن توابع در یک ماژول دیگر با مشخص کردن نام ماژول و در دنباله ی آن یک نقطه "." و نام تابع

ترکیب بندی:استفاده از یک عبارت به عنوان بخشی از یک گزاره به عنوان بخشی از یک گزاره بزرگ تر یا یک عبارت به عنوان بخشی از عبارت بزرگتر

روال اجرا:ترتیب اجرای عبارات

نمودارپشته:یک نمایش گرافیکی از پشته ای توابع است که توابع ، متغیر های آن ها و مقادیری که به آن متغیر ها ارجاع داده شده اند را نشان میدهد

قاب:یک مستطیل در یک نمودار پشته که یک صدازدن تابع را نمایش می دهد.شامل متغیر های محلی و پارامتر های تابع است.

لیست ردیابی:لیستی از توابع که در حال اجرا هستند ، موقع بروز خطا ها چاپ می شود.

#### ۳.۱۴ تمرین ها

تمرین ۳.۱ : یک تابع به نام right_justify بنویسید که یک رشته به نام s را به عنوان پارامتر بگیرد و رشته را با تعداد کافی فاصله قبل از آن چاپ کند به گونه ای که آخرین حرف رشته در ردیف ۷۰ ام نمایشگر قرار بگیرد

>>> right_justify(‘monty’)

monty

راهنمایی: از الحاق و تکرار رشته استفاده کنید. همچنین پایتون دارای یک تابع توکار به نام len است که طول رشته را برمیگرداندبه همین شکل ، حاصل ( 'len('monty برابر ۵ خواهد بود.

تمرین ۳.۲ یک شی تابع یک مقدار است که شما میتوانید آن را به یک متغیر ارجاع دهید یا به عنوان آرگومان به تابع بفرستید. به عنوان مثال do_twice یک تابع است که یک شی تابع را به عنوان آرگومان میگیرد و دوبار آن را صدا می زند:

def do_twice(f):

f()

f()

در اینجا یک مثال از استفاده از do_twice میبینیم که یک تابع به نام print_spam را دوبار فراخوانی می کند:

def print_spam():

print(‘spam’)

do_twice(print_spam)

۱- این مثال را در یک برنامه بنویسید و آن را امتحان کنید.\ ۲-تابع do_twice را به گونه ای تغییر دهید که دو آرگومان بگیرد: یک شی تابع و یک مقدار و تابع twice را صدا بزند و مقدار را به عنوان آرگومان به آن بدهد

۳- تعریف تابع print_twice را از همین فصل به برنامه خود کپی کنید.

۴-از نسخه تغییر داده شده ی do_twice برای دوبار صدا زدن print_twice استفاده کنید و 'spam' را دوبار به عنوان آرگومان به آن بفرستید.

۵- یک تابع جدید به نام do_four تعریف کنید که یک شی تابع و یک مقدار بگیرد و تابع را چهار بار صدا بزند و مقدار را به عنوان یک پارامتر پاس بدهد.در بدنه ی این تابع باید فقط دو عبارت باشد

نه چهار عبارت.

راه حل: http://thinkpython2.com/code/do_four.py

تمرین ۳.۳ : تذکر این تمرین باید تنها توسط عبارات و امکاناتی که تا کنون یاد گرفته ایم حل شود.

۱- تابعی بنویسید که شبکه توری زیر را رسم کند:

راهنمایی: برای چاپ کردن بیش از یک مقدار در هر خط ، شما میتوانید مجموعه ای از عبارات که با ویرگول از هم جدا شده اند چاپ کنید:

print (‘+’ , ‘-’)

به طور پیشفرض ، print به خط بعدی می رود ولی شما میتوانید از رفتار را تغییر بدهید و یک فاصله در انتهای خط قرار بدهید:

print (‘+’ , end=’ ‘)

print (‘-’)

خروجی عبارات بالا '- + ' است.

۲- یک تابع بنویسید که یک شبکه توری مشابه را در چهار ردیف و چهار ستون رسم کند.

راه حل: http://thinkpython2.com/code/grid.py

منبع: این تمرین بر اساس تمرینات کتاب

Oualline, Practical C Programming, Third Edition,O’Reilly Media, 1997.

بوده است.

پایان فصل ۳

[^1]: function objects

[^2]: error message

[^3]: Flow of execution

[^8]: stack diagrams

[^9]: state diagram

[^12]: fruitful functions

[^13]: void functions

[^15]: A. Conan Doyle, The Sign of Four

[^16]: Linus Torvalds